﻿using Microsoft.Win32;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Xml;
using System.Xml.Linq;
using T810_CAN.CAN;
using T810_CAN.COMMON;

namespace T810_CAN
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private const uint PMU_ID = 0x08;
        private const uint WDU_ID = 0x04;
        private const uint BDU_ID = 0x07;
        private const uint HOU_ID = 0x05;
        private const uint RCU_ID = 0x06;


        private DispatcherTimer dispatcherTimer = new DispatcherTimer();
        private ConcurrentDictionary<UInt32, List<Signal>> signalMap = new ConcurrentDictionary<UInt32, List<Signal>>();

        CANalyst_II can = new CANalyst_II();
        public MainWindow()
        {
            InitializeComponent();
            can.CAN_Frame_Received += Can_CAN_Frame_Received;

            dispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
            dispatcherTimer.Tick += DispatcherTimer_Tick;
            dispatcherTimer.Start();
        }

        private void DispatcherTimer_Tick(object? sender, EventArgs e)
        {

        }

        private void Can_CAN_Frame_Received(CanFrame frame)
        {
            Trace.WriteLine(frame.ToString());
            CanFrameProcess(frame);
        }

        private void cbCanDevice_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            cbCanDevice.Items.Clear();
        }

        private void btnCanOpen_Click(object sender, RoutedEventArgs e)
        {
            can.Start();
        }

        private void CanFrameProcess(CanFrame frame)
        {
            switch (frame.ID)
            {
                case 0x410 + PMU_ID: //PMU状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtPMUKey.Text = (frame.Data[0] & (0x01 << 1 - 1)).ToString();
                        txtPMUEmergency.Text = (frame.Data[0] >> 1 & (0x01 << 1 - 1)).ToString();
                        txtPMUChargeAutoDetect.Text = (frame.Data[0] >> 2 & (0x01 << 1 - 1)).ToString();
                        txtPMUChargeManualDetect.Text = (frame.Data[0] >> 3 & (0x01 << 1 - 1)).ToString();
                        txtBMSStatus.Text = (frame.Data[0] >> 4 & (0x01 << 2 - 1)).ToString();
                        txtPMULeftDetect.Text = (frame.Data[0] >> 6 & (0x01 << 1 - 1)).ToString();
                        txtPMURightDetect.Text = (frame.Data[0] >> 7 & (0x01 << 1 - 1)).ToString();
                    });
                    break;
                case 0x420 + PMU_ID: //BMS状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtBMSCurrent.Text = ((((UInt16)frame.Data[0] << 8 + (UInt16)frame.Data[1])) / 100.0f / 1000).ToString();
                        txtBMSVoltage.Text = ((((UInt16)frame.Data[3] << 8 + (UInt16)frame.Data[2])) / 100.0f / 1000).ToString();
                        txtBMSSoc.Text = frame.Data[4].ToString();
                        txtBMSTemp.Text = (frame.Data[5] - 40).ToString();
                        txtBMSStatus.Text = frame.Data[6].ToString();

                    });
                    break;
                case 0x410 + WDU_ID: //WDU行走电机状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtWDUStatus.Text = frame.Data[0].ToString();
                        txtWDUErrorCode.Text = frame.Data[1].ToString();
                        txtWDUWalkCurrent.Text = ((((UInt16)frame.Data[2] << 8 + (UInt16)frame.Data[3])) / 100.0f).ToString();
                        txtWDUWalkSpeed.Text = ((Int16)(((UInt16)frame.Data[4] << 8 + (UInt16)frame.Data[5]))).ToString();
                        txtWDUWalkTorque.Text = ((((UInt16)frame.Data[7] << 8 + (UInt16)frame.Data[6])) / 1000.0f).ToString();

                    });
                    break;
                case 0x420 + WDU_ID: //WDU转向电机状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtWDURotateEncoder.Text = BitConverter.ToInt32(frame.Data, 0).ToString();
                        txtWDURotateAngle.Text = (BitConverter.ToInt16(frame.Data, 4) / 100.0f).ToString();
                        txtWDURotateErrorCode.Text = BitConverter.ToInt16(frame.Data, 6).ToString();
                    });
                    break;
                case 0x430 + WDU_ID: //WDU 行走电机状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtWDUEmergency.Text = frame.Data[4].ToString();
                        txtWDUCtrlBy.Text = frame.Data[5].ToString();
                    });
                    break;
                case 0x410 + BDU_ID: //BDU状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtBDUStatus.Text = (frame.Data[0] & (0x01 << 3 - 1)).ToString();
                        txtBDUWorkMode.Text = (frame.Data[0] >> 3 & (0x01 << 3 - 1)).ToString();
                        txtBDUControlStatus.Text = (frame.Data[0] >> 6 & (0x01 << 2 - 1)).ToString();

                        txtBDULeftBrushGear.Text = (frame.Data[1] & (0x01 << 3 - 1)).ToString();
                        txtBDURightBrushGear.Text = (frame.Data[1] >> 3 & (0x01 << 3 - 1)).ToString();
                        txtBDUSuckPush.Text = (frame.Data[1] >> 6 & 0x01).ToString();
                        txtBDUBrushPush.Text = (frame.Data[1] >> 7 & 0x01).ToString();

                        txtBDUSuckGear.Text = (frame.Data[2] & (0x01 << 3 - 1)).ToString();
                        txtBDUWaterGear.Text = (frame.Data[2] >> 3 & (0x01 << 3 - 1)).ToString();
                        txtBDUDirtyRelay.Text = (frame.Data[2] >> 6 & (0x01 << 1 - 1)).ToString();
                        txtBDUCleanRelay.Text = (frame.Data[2] >> 7 & (0x01 << 1 - 1)).ToString();

                        txtBDUCleanHeight.Text = (frame.Data[3] & (0x01 << 7 - 1)).ToString();
                        txtBDUCleanStatus.Text = (frame.Data[3] >> 7 & (0x01 << 1 - 1)).ToString();
                        txtBDUDirtyHeight.Text = (frame.Data[4] & (0x01 << 7 - 1)).ToString();
                        txtBDUDirtyStatus.Text = (frame.Data[4] >> 7 & (0x01 << 1 - 1)).ToString();

                        txtBDUSpeakerStatus.Text = (frame.Data[5] & (0x01 << 1 - 1)).ToString();
                        txtBDUTopLedStatus.Text = (frame.Data[5] >> 1 & (0x01 << 1 - 1)).ToString();
                        txtBDUFrontLedStatus.Text = (frame.Data[5] >> 2 & (0x01 << 1 - 1)).ToString();

                        txtBDULedStatus.Text = (frame.Data[6]).ToString();

                    });
                    break;
                case 0x410 + HOU_ID: //HOU状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtHOUStatus.Text = (frame.Data[0] & (0x01 << 2 - 1)).ToString();
                        txtHOUControlStatus.Text = (frame.Data[0] >> 2 & (0x01 << 2 - 1)).ToString();
                        txtHOUKeySpeaker.Text = (frame.Data[0] >> 4 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyFrontLed.Text = (frame.Data[0] >> 5 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyCleanStart.Text = (frame.Data[0] >> 6 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeySuckStart.Text = (frame.Data[0] >> 7 & (0x01 << 1 - 1)).ToString();

                        txtHOUKeyEmergency.Text = (frame.Data[1] >> 0 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyCrash.Text = (frame.Data[1] >> 1 & (0x01 << 1 - 1)).ToString();
                        txtHOUPress.Text = (frame.Data[1] >> 2 & (0x01 << 1 - 1)).ToString();
                        txtHOUEpf.Text = (frame.Data[1] >> 3 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyForward.Text = (frame.Data[1] >> 4 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyBackward.Text = (frame.Data[1] >> 5 & (0x01 << 1 - 1)).ToString();

                        txtHOUKeyBackCar.Text = (frame.Data[1] >> 6 & (0x01 << 1 - 1)).ToString();
                        txtHOUKeyPause.Text = (frame.Data[1] >> 7 & (0x01 << 1 - 1)).ToString();
                        txtHOUSpeed.Text = (frame.Data[2]).ToString();
                        txtHOUSlope.Text = (frame.Data[3]).ToString();

                        txtHOUErrorCode.Text = (((UInt16)frame.Data[4] << 8 + (UInt16)frame.Data[5])).ToString();
                    });
                    break;
                case 0x420 + RCU_ID: //RCU状态
                    this.Dispatcher.Invoke(() =>
                    {
                        txtRCULeftBrushGear.Text = (frame.Data[0] >> 2 & (0x01 << 3 - 1)).ToString();
                        txtRCURightBrushGear.Text = (frame.Data[0] >> 5 & (0x01 << 3 - 1)).ToString();
                        txtRCUSuckGear.Text = (frame.Data[1] & (0x01 << 3 - 1)).ToString();
                        txtRCUWaterGear.Text = (frame.Data[1] >> 3 & (0x01 << 3 - 1)).ToString();
                        txtRCUSuckPush.Text = (frame.Data[1] >> 6 & (0x01 << 2 - 1)).ToString();
                        txtRCUBrushPush.Text = (frame.Data[2] >> 0 & (0x01 << 2 - 1)).ToString();
                        txtRCUDirtyRelay.Text = (frame.Data[2] >> 2 & (0x01 << 1 - 1)).ToString();
                        txtRCUCleanRelay.Text = (frame.Data[2] >> 3 & (0x01 << 1 - 1)).ToString();

                        txtRCUForwardBackward.Text = (frame.Data[2] >> 4 & (0x01 << 1 - 1)).ToString();
                        txtRCUTopLed.Text = (frame.Data[2] >> 5 & (0x01 << 1 - 1)).ToString();
                        txtRCUFrontLed.Text = (frame.Data[2] >> 6 & (0x01 << 1 - 1)).ToString();
                        txtRCUPause.Text = (frame.Data[2] >> 7 & (0x01 << 1 - 1)).ToString();

                        txtRCULed.Text = (frame.Data[3]).ToString();
                    });
                    break;
            }
        }

        private void btnConfig_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.DefaultExt = "xml";
            ofd.Filter = "xml文件|*.xml";
            if (ofd.ShowDialog() == true)
            {
                //process.LoadProject(ofd.FileName);
            }
        }

        private void loadProjectFile(string fileName)
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(fileName);

            Dictionary<string, Signal> signalMap = new Dictionary<string, Signal>();
            foreach (XmlElement n in xml.SelectNodes($"/root/signals"))
            {
                try
                {
                    string signal_name = n.GetAttribute("name");
                    string signal_description = n.GetAttribute("name");
                    //UInt32 signal_canid = n.GetAttribute("id");

                    //Signal signal = new Signal()
                    //{
                    //    Name =
                    //    Description = "",
                    //    CanId = n.GetAttribute("id"),
                    //    StartBit = Common.str2hex(n.GetAttribute("data")),
                    //    BitLength = Common.str2hex(n.GetAttribute("data")),
                    //    Ac = Common.str2hex(n.GetAttribute("data")),
                    //    BitLength = Common.str2hex(n.GetAttribute("data")),
                    //};
                    //signalMap.Add(signal.Name, signal);
                }
                catch (Exception)
                {

                    throw;
                }

            }


            //XmlElement signalElemnet = (XmlElement)xml.SelectSingleNode("/root/signal");
            //return new CAN_Config()
            //{
            //    DeviceType = Convert.ToUInt32(el_can_config.GetAttribute("device_type")),
            //    DeviceIndex = Convert.ToUInt32(el_can_config.GetAttribute("device_index")),
            //    CANIndex = Convert.ToUInt32(el_can_config.GetAttribute("can_index")),
            //    AccCode = Convert.ToUInt32(el_can_config.GetAttribute("AccCode"), 16),
            //    AccMask = Convert.ToUInt32(el_can_config.GetAttribute("AccMask"), 16),
            //    Filter = Convert.ToByte(el_can_config.GetAttribute("Filter")),   //0或1接收所有帧。2标准帧滤波，3是扩展帧滤波。
            //    Mode = Convert.ToByte(el_can_config.GetAttribute("Mode")),       //模式，0表示正常模式，1表示只听模式,2自测模式
            //    Timing0 = Convert.ToByte(el_can_config.GetAttribute("Timing0"), 16), //波特率参数，具体配置，请查看二次开发库函数说明书。
            //    Timing1 = Convert.ToByte(el_can_config.GetAttribute("Timing1"), 16),
            //};

        }
    }
}